"""
Author: Jian SuiYue kaohx0214@yeah.net
Date: 2025-04-30 22:08:53
LastEditTime: 2025-05-20 12:30:23
FilePath: LibraryManagerStudio/web/routes/token_api.py
"""
import datetime as dt
import uuid

import jwt
from alembic.util import status
from fastapi import HTTPException, status, Depends

from ...database import DBManager
from ...datamodel import Token, User
from loguru import logger

SECRET_KEY = "1Elysia1TruE1Love1"  # this secret key is temporary, myabe will update 
ALGORITHM = "HS256"


def generate_jwt(user_id: int, db: DBManager) -> str:
    """
    generate jwt
    """
    jti = str(uuid.uuid4())  # birth only ont JWT ID
    expires = dt.datetime.now(dt.UTC) + dt.timedelta(hours=4)

    payload = {
        "sub": str(user_id),  # subject: uid
        "jti": jti,  # JWT ID Used for replay protection
        "exp": expires,  # expires time
    }

    token = jwt.encode(payload, SECRET_KEY, algorithm=ALGORITHM)

    _token = Token(jti=jti, user_id=user_id, token=token, expires_at=expires)
    # save token to sqlite table
    result = db.upsert(_token)
    if not result.status or not result.data:
        raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="Unexpected Error occur at create token")

    return token


def validate_jwt(token: str, db: DBManager):
    """
    verify token
    """
    try:
        payload = jwt.decode(jwt=token, key=SECRET_KEY, algorithms=[ALGORITHM])
        jti = payload["jti"]
        uid = int(payload["sub"])  # subject
        
        if not is_token_valid(jti, db):
            raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Token jti Invalid")
       
        user_exist = db.get(User, filters={"id": uid})
        
        if not user_exist.data or not user_exist.status:
            raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Token is invalid")
        return uid
    except Exception as e:
        raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail=f"Unexpted error: {e}")


def revoke_token(user_id: int, db: DBManager):
    """
    delete token
    """
    db.delete(Token, filters={"user_id": user_id})


def is_token_valid(jti: str, db: DBManager) -> bool:
    """
    token is valid or not
    """
    result = db.get(Token, filters={"jti": jti})

    if not result.status or not result.data:
        return False  # JTI 不存在

    expires_at = result.data[0].expires_at
    now = dt.datetime.now(dt.UTC)

    now_y, now_m, now_d, now_h, now_min, now_s = now.year, now.month, now.day, now.hour, now.minute, now.second
    expires_at_y, expires_at_m, expires_at_d = expires_at.year, expires_at.month, expires_at.day
    expires_at_h, expires_at_min, expires_at_s = expires_at.hour, expires_at.minute, expires_at.second

    logger.info(f"now: {now_y}-{now_m}-{now_d}-{now_h}-{now_min}-{now_s}")
    logger.info(f"expires: {expires_at_y}-{expires_at_m}-{expires_at_d}-{expires_at_h}-{expires_at_min}-{expires_at_s}")

    # verify exprise time
    #if expires_at_y < now_y and expires_at_m < now_m and expires_at_d < now_d:
    #    return False
    #elif expires_at_h < now_h and expires_at_min < now_min and expires_at_s < now_s:
    #    return False

    return True
